package com.project.srtp.secure.service.impl;

import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.project.srtp.secure.common.biz.UserContextHolder;
import com.project.srtp.secure.dao.entity.DecryptionSenderKeyDO;
import com.project.srtp.secure.dao.entity.PartyDO;
import com.project.srtp.secure.dto.req.CreateSessionReqDTO;
import com.project.srtp.secure.dto.req.GetSessionIdReqDTO;
import com.project.srtp.secure.dto.resp.CreateSessionRespDTO;
import com.project.srtp.secure.dto.resp.GetSessionIdRespDTO;
import com.project.srtp.secure.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static com.project.srtp.secure.common.constant.SessionTypeConstant.SINGLE;

/**
 * @author 曹行阳
 * @version 0.1
 * @date 2025/6/16 18:38
 */
@Service
@RequiredArgsConstructor
public class SessionServiceImpl implements SessionService {
    private final PartyService partyService;
    private final EncryptionSenderKeyService encryptionSenderKeyService;
    private final DecryptionSenderKeyService decryptionSenderKeyService;

    @Override
    public CreateSessionRespDTO createSession(CreateSessionReqDTO request) {
        Integer type = request.getType();
        List<String> result = new ArrayList<>();
        if (Objects.equals(type, SINGLE)) {
            result = createSingleSession(request);
        }
        if (result.size() < 2 || result.get(0).isEmpty() || result.get(1).isEmpty()) {
            throw new RuntimeException("创建失败");
        }
        return CreateSessionRespDTO.builder()
                .SessionId(result.get(0))
                .partyId(result.get(1))
                .build();
    }

    @Override
    public String getSessionId(GetSessionIdReqDTO request) {
        String forUserId = request.getForUserId();
        String ofUserId = request.getOfUserId();
        Optional<String> existingPartyIdOpt = partyService.findExistingPartyId(forUserId, ofUserId);
        String partyId;
        boolean alreadyExists = existingPartyIdOpt.isPresent();
        String sessionId = "";
        if (alreadyExists) {
            partyId = existingPartyIdOpt.get();
            sessionId = encryptionSenderKeyService.getSessionIdByPartyId(partyId);
        }
        return sessionId;
    }

    @Override
    public List<GetSessionIdRespDTO> getAllSessionId(String userId) {
        LambdaQueryWrapper<DecryptionSenderKeyDO> queryWrapper = Wrappers.lambdaQuery(DecryptionSenderKeyDO.class)
                .eq(DecryptionSenderKeyDO::getOfUserId, userId);
        return decryptionSenderKeyService.getAllSessionId(userId);
    }

    private List<String> createSingleSession(CreateSessionReqDTO request) {
        List<String> toUserIds = request.getToUserIds();
        String toUserId = toUserIds.get(0);                 //ALICE
        String fromUserId = request.getFromUserId();        //BOB
                Optional<String> existingPartyIdOpt = partyService.findExistingPartyId(fromUserId, toUserId);       //有没有建群
        String partyId;
        boolean alreadyExists = existingPartyIdOpt.isPresent();
        String sessionId = "";
        if (alreadyExists) {
            partyId = existingPartyIdOpt.get();
            sessionId = encryptionSenderKeyService.getSessionIdByPartyId(partyId);          //partyId获取SessionId
        } else {
            partyId = UUID.randomUUID().toString();         //UUID随机生成的
            String partyHash = calculateSha256(toUserId + fromUserId);      //完整性验证
            int chainId = 0;        //链ID

            //0  ->  预共享密钥组生命周期50次
            //1  ->   重新生成sessionId
            PartyDO toUserpartyDO = PartyDO.builder()
                    .individual(Boolean.TRUE)
                    .userId(toUserId)
                    .partyId(partyId)
                    .partyHash(partyHash)
                    .build();
            PartyDO fromUserpartyDO = PartyDO.builder()
                    .individual(Boolean.TRUE)
                    .userId(fromUserId)
                    .partyId(partyId)
                    .partyHash(partyHash)
                    .build();
            partyService.createSingleSession(toUserpartyDO);
            partyService.createSingleSession(fromUserpartyDO);
            sessionId = partyId + chainId;
        }
        return List.of(sessionId, partyId);
    }


    /**
     * 计算字符串的SHA-256哈希值
     *
     * @param input 输入字符串
     * @return 64字符的十六进制哈希值
     */
    private static String calculateSha256(String input) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hashBytes = digest.digest(input.getBytes());

            // 将字节数组转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : hashBytes) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("SHA-256算法不可用", e);
        }
    }
}
